
#include <string.h>
#include "BSP_Delay.h"

#include "CardCpuPrivate.h"
#include "ISO14443p3a.h"
#include "ISO14443p4a.h"
#include "ISO14443p4.h"

#include "WCI.h"

static CpuCard_T cpuCard;

static int PICC_TypeA_Check(uint8_t count, uint8_t* atqa){
	int i;
	int ret = -1;
	uint8_t tatqa[4];
	
	ISO14443A_SetMode();
	for(i = 0; i < count; i++){
		BSP_Delay_ms(10);
		ret = ISO14443A_WakeupA(tatqa);
		if(!ret){
			if(atqa){
				memcpy(atqa, tatqa, 2);
			}
			return ret;
		}
	}
	
	return -1;
}


static int PICC_TypeA_Anti(uint8_t buf[], uint8_t* ulen, uint8_t* sak)
{
	int ret;
	
	ret = ISO14443A_SimpleAntiLoop(buf, ulen, sak);
	if(!(ret == 0 || ret == CmdS_NotCompliant)){
		return -2;
	}
	return 0;
}

int PICC_TypeA_Init(uint8_t count, uint8_t* uid, uint8_t* ulen, uint8_t* sak){
	uint8_t tuid[16];
	uint8_t tlen;
	uint8_t tsak;
	
	int ret = PICC_TypeA_Check(count, NULL);
	if(ret){
		return ret;
	}
	ret = PICC_TypeA_Anti(tuid, &tlen, &tsak);
	if(ret){
		return ret;
	}
	if(uid){
		memcpy(uid, tuid, tlen);
	}
	if(ulen){
		*ulen = tlen;
	}
	if(sak){
		*sak = tsak;
	}
	return ret;
}


int PICC_TypeA_Init2(uint8_t count, uint8_t* uid, uint8_t* ulen, uint8_t* sak, uint8_t* atqa){
	uint8_t tuid[16];
	uint8_t tlen;
	uint8_t tsak;
	
	int ret = PICC_TypeA_Check(count, atqa);
	if(ret){
		return ret;
	}
	ret = PICC_TypeA_Anti(tuid, &tlen, &tsak);
	if(ret){
		return ret;
	}
	if(uid){
		memcpy(uid, tuid, tlen);
	}
	if(ulen){
		*ulen = tlen;
	}
	if(sak){
		*sak = tsak;
	}
	return ret;
}

int PICC_TypeA_Setup(uint8_t* ats){
	uint8_t tats[32];
	if(ISO14443p4a_RATS(0, 8, tats)){
		return - 3;
	}
	
	ISO14443p4a_GetParams(tats, &cpuCard.params);
	if(ats){
		memcpy(ats, tats, tats[0]);
	}
	return 0;
}

int PICC_TypeA_Active(uint8_t* ats){
	uint8_t tats[32];
	int ret;
	uint8_t sak;
	
	ret = PICC_TypeA_Init(2, 0, 0, &sak);
	if(ret){
		return ret;
	}
	if(!(sak & 0x20)){
		return -3;
	}
	if(ISO14443p4a_RATS(0, 8, tats)){
		return - 3;
	}
	
	ISO14443p4a_GetParams(tats, &cpuCard.params);
	if(ats){
		memcpy(ats, tats, tats[0]);
	}
	return 0;
}

int PICC_TypeA_Deactive(void){
	ISO14443A_Halt(0);
	return 0;
}

int PICC_PowerOn(uint8_t * ats){
	WCI_SetRf(0);
	BSP_Delay_ms(10);
	WCI_SetRf(1);
	BSP_Delay_ms(10);

	return PICC_TypeA_Active(ats);
}

int PICC_PowerOff(void){
	PICC_TypeA_Deactive();
	WCI_SetRf(0);
	return 0;
}

int PICC_Raw_ExchangeAPDU(uint8_t capdu[], uint16_t clen, uint8_t rapdu[], uint16_t* rlen){
	unsigned int rxlen = 0;
	int ret;
	ret = ISO14443p4_Exchange(&cpuCard, capdu, clen, rapdu , &rxlen);
	
	if(ret){
		return -1;
	}
	
	*rlen = rxlen;	
	return ret;
}

int PICC_ExchangeAPDU(uint8_t capdu[], uint16_t clen, uint8_t rapdu[], uint16_t* rlen){
	static uint8_t apdu_buf[270];
	unsigned int rxlen = 0;
	int ret;

	ret = ISO14443p4_Exchange(&cpuCard, capdu, clen, apdu_buf , &rxlen);
	
	if(ret){
		return ret;
	}
	
	if(rxlen < 2){
		return -2;
	}

	if(memcmp((uint8_t []){0x90, 0x00}, &apdu_buf[rxlen - 2], 2)){
		return 1;
	}

	if(rlen){
		*rlen = rxlen - 2;
	}

	if(rapdu){
		memcpy(rapdu, apdu_buf, rxlen - 2);
	}

	return 0;
}


